package cn.wizzer.app.web.modules.controllers.platform.bus;


import cn.wizzer.app.bus.modules.models.BusinessFileInfo;
import cn.wizzer.app.bus.modules.models.InspectionItem;
import cn.wizzer.app.bus.modules.models.InspectionStandard;
import cn.wizzer.app.bus.modules.models.equipment.BusEquipment;
import cn.wizzer.app.bus.modules.services.BusEquipmentService;
import cn.wizzer.app.bus.modules.services.BusinessFileInfoService;
import cn.wizzer.app.bus.modules.services.InspectionItemService;
import cn.wizzer.app.bus.modules.services.InspectionStandardService;
import cn.wizzer.app.sys.modules.models.Sys_role;
import cn.wizzer.app.sys.modules.services.SysDictService;
import cn.wizzer.app.sys.modules.services.SysRoleService;
import cn.wizzer.app.web.commons.base.Globals;
import cn.wizzer.app.web.commons.slog.annotation.SLog;
import cn.wizzer.app.web.commons.utils.DoExcelUtil;
import cn.wizzer.app.web.commons.utils.PageUtil;
import cn.wizzer.app.web.commons.utils.StringUtil;
import cn.wizzer.app.web.modules.controllers.open.file.UploadController;
import cn.wizzer.framework.base.Result;
import net.sf.json.JSONObject;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.authz.annotation.RequiresAuthentication;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.nutz.aop.interceptor.ioc.TransAop;
import org.nutz.dao.Chain;
import org.nutz.dao.Cnd;
import org.nutz.dao.Sqls;
import org.nutz.ioc.aop.Aop;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.lang.Lang;
import org.nutz.lang.Strings;
import org.nutz.lang.Times;
import org.nutz.lang.util.NutMap;
import org.nutz.log.Log;
import org.nutz.log.Logs;
import org.nutz.mvc.adaptor.JsonAdaptor;
import org.nutz.mvc.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.util.*;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.stream.Collectors;

/**
 * 标准管理
 */
@IocBean
@At("/platform/bus/ins_standard/")
public class InspectionStandardController {

    private static final Log log = Logs.get();

    @Inject
    private InspectionStandardService inspectionStandardService;

    @Inject
    private InspectionItemService inspectionItemService;
    @Inject
    private SysDictService sysDictService;
    @Inject
    private BusinessFileInfoService businessFileInfoService;
    @Inject
    BusEquipmentService busEquipmentService;

    @Inject
    SysRoleService sysRoleService;



    /**
     * 列表页面跳转
     * （尽量不要在跳转页面时带参数，为以后可能的前后端改造减少工作量）
     */
    @At("")
    @Ok("beetl:/platform/bus/inspectionStandard/index.html")
    @RequiresPermissions("bus.ins_standard.management")
    public void index(HttpServletRequest req) {
        req.setAttribute("yplxMap", JSONObject.fromObject(sysDictService.getCodeMap("yplx")));
        String sysadminRoleid = sysRoleService.fetch(Cnd.where("code", "=", "sysadmin")).getId();
        List<Sys_role> roles = StringUtil.getPlatformUser().getRoles();
        String role = roles.stream().map(t->t.getId()).collect(Collectors.joining(","));
        if (role.indexOf(sysadminRoleid)!=-1) {
            req.setAttribute("isAdmin", true);
        }else{
            req.setAttribute("isAdmin", false);
        }
    }

    /**
     * 详情页面跳转
     * 以后如果改为前后端分离，此方法作废，在前端页面跳转时带上参数
     * 然后用ajax请求数据即可
     */
    @At("/view/?")
    @Ok("beetl:/platform/bus/inspectionStandard/showView.html")
    @RequiresPermissions("bus.ins_standard.management")
    public void view(String standardId, HttpServletRequest req) {
        req.setAttribute("standardId", standardId);
        req.setAttribute("yplxMap", JSONObject.fromObject(sysDictService.getCodeMap("yplx")));
        req.setAttribute("object", JSONObject.fromObject(inspectionStandardService.fetchLinks(inspectionStandardService.fetch(standardId), "inspectionItems",Cnd.NEW().asc("inspectionItemOrder"))));
    }

//    @At("/view/data/?")
//    @Ok("json")
//    @RequiresPermissions("bus.ins_standard.management.view")
//    public Object viewData(String id) {
//        try {
//            return Result.success().addData(inspectionStandardService.fetchLinks(inspectionStandardService.fetch(id), "inspectionItems"));
//        } catch (Exception e) {
//            return Result.error();
//        }
//
//    }

    /**
     * 检验标准
     *
     * @param pageNumber             开始页数
     * @param pageSize               分页大小
     * @param pageOrderName          排序字段名称
     * @param pageOrderBy            排序方式
     * @param productTypeCode        产品类型编码
     * @param productName            产品名称
     * @param inspectionStandardName 检验标准
     * @return
     */
    @At
    @Ok("json:full")
    @RequiresPermissions("bus.ins_standard.management.list")
    public Object data(
            @Param("pageNumber") int pageNumber,
            @Param("pageSize") int pageSize,
            @Param("pageOrderName") String pageOrderName,
            @Param("pageOrderBy") String pageOrderBy,
            @Param("productTypeCode") String productTypeCode,
            @Param("productName") String productName,
            @Param("inspectionStandard") String inspectionStandardName

    ) {
        try {
            String sql = "select * from bus_ins_standard where delFlag = 0 ";
            if(StringUtils.isNotBlank(productTypeCode)){
                sql+=" and productTypeCode like '"+productTypeCode+"%' ";
            }
            if(StringUtils.isNotBlank(productName)){
                sql+=" and productName like '%"+productName+"%' ";
            }
            if(StringUtils.isNotBlank(inspectionStandardName)){
                sql+=" and inspectionStandard like '%"+inspectionStandardName+"%' ";
            }
            sql+=StringUtil.dataScopeFilter("");
            if (Strings.isNotBlank(pageOrderName) && Strings.isNotBlank(pageOrderBy)) {
                if ("ascending".equalsIgnoreCase(pageOrderBy)) {
                    sql+= " order by "+pageOrderName+" asc,opAt desc ";
                } else {
                    sql+= " order by "+pageOrderName+" desc,opAt desc ";
                }
            }else{
                sql+= " order by opAt desc ";
            }

            return Result.success().addData(inspectionStandardService.listPage(pageNumber, pageSize, Sqls.create(sql)));
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return Result.error();
        }


    }


    @Aop(TransAop.READ_COMMITTED)
    @AdaptBy(type = JsonAdaptor.class)
    @At()
    @Ok("json")
    @RequiresPermissions("bus.ins_standard.management.add")
    @SLog(tag = "新建标准", msg = "标准名称:${args[0].productTypeName}")
    public Object addDo(@Param("standard") InspectionStandard inspectionStandard) {
        try {
            inspectionStandard.setOperatorName(StringUtil.getPlatformUsername());
            inspectionStandard.setDisabled(false);
            this.inspectionStandardService.insertWith(inspectionStandard, "inspectionItems");
            this.inspectionStandardService.clearCache();
            return Result.success();
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return Result.error();
        }
    }

    @Aop(TransAop.READ_COMMITTED)
    @At()
    @Ok("json")
    @RequiresAuthentication
    @SLog(tag = "上传模板", msg = "fileId:${args[0]}")
    public Object upExcel(@Param("fileId") String fileId) {
        try {
            businessFileInfoService.execute(Sqls.create(" update bus_file_info set delFlag=1 where infoType='inspectionStandard' "));
            BusinessFileInfo reportheaderTemplate = businessFileInfoService.fetch(fileId);
            reportheaderTemplate.setInfoType("inspectionStandard");
            reportheaderTemplate.setDelFlag(false);
            businessFileInfoService.update(reportheaderTemplate);
            return Result.success();
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return Result.error();
        }
    }

    @At()
    @Ok("json")
    @RequiresAuthentication
    public Object downExcel(HttpServletRequest req) {
        try {
            BusinessFileInfo businessFileInfo = businessFileInfoService.fetch(Cnd.NEW().where("infoType", "=","inspectionStandard").and("delFlag", "=", false));
            return Result.success(businessFileInfo);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return Result.error();
        }
    }

    @At("/edit/?")
    @Ok("json")
    @GET
    @RequiresPermissions("bus.ins_standard.management.edit")
    public Object edit(String id) {
        try {
            return Result.success()
                    .addData(
                            inspectionStandardService.fetchLinks(
                                    inspectionStandardService.fetch(id), "inspectionItems",Cnd.NEW().asc("inspectionItemOrder")
                            )
                    );
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return Result.error();
        }

    }


    @Aop(TransAop.READ_COMMITTED)
    @AdaptBy(type = JsonAdaptor.class)
    @At
    @Ok("json")
    @RequiresPermissions("bus.ins_standard.management.edit")
    @SLog(tag = "修改标准", msg = "产品名称:${args[0].inspectionStandard}")
    public Object editDo(@Param("standard") InspectionStandard inspectionStandard) {
        try {
            inspectionStandard.setOpBy(StringUtil.getPlatformUid());
            inspectionStandard.setOperatorName(StringUtil.getPlatformUsername());
            inspectionStandard.setOpAt(Times.getTS());
            InspectionStandard standard = this.inspectionStandardService.insertOrUpdate(inspectionStandard);
            List<InspectionItem> inspectionItems = inspectionStandard.getInspectionItems();
            for (InspectionItem item : inspectionItems) {
                item.setOpBy(StringUtil.getPlatformUid());
                item.setOpAt(Times.getTS());
                item.setInsStandardId(standard.getId());
                this.inspectionItemService.insertOrUpdate(item);
                this.inspectionItemService.deleteCache(item.getId());
            }
            this.inspectionStandardService.deleteCache(inspectionStandard.getId());
            return Result.success();
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return Result.error();
        }
    }

    @At("/enable/?")
    @Ok("json")
    @RequiresPermissions("bus.ins_standard.management.edit")
    @SLog(tag = "启用标准", msg = "标准ID:${args[1].getAttribute('standardId')}")
    public Object enable(String standardId, HttpServletRequest req) {
        try {
            req.setAttribute("standardId", standardId);
            this.inspectionStandardService.update(Chain.make("disabled", false), Cnd.where("id", "=", standardId));
            this.inspectionStandardService.deleteCache(standardId);
            return Result.success();
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return Result.error();
        }
    }

    @At("/disable/?")
    @Ok("json")
    @RequiresPermissions("bus.ins_standard.management.edit")
    @SLog(tag = "禁用标准", msg = "标准:${args[1].getAttribute('templateId')}")
    public Object disable(String standardId, HttpServletRequest req) {
        try {
            req.setAttribute("standardId", standardId);
            this.inspectionStandardService.update(Chain.make("disabled", true), Cnd.where("id", "=", standardId));
            this.inspectionStandardService.deleteCache(standardId);
            return Result.success();
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return Result.error();
        }
    }

    @At("/delete/?")
    @Ok("json")
    @RequiresPermissions("bus.ins_standard.management.delete")
    @SLog(tag = "删除标准", msg = "标准ID:${args[1].getAttribute('templateId')}")
    public Object delete(String standardId, HttpServletRequest req) {
        try {
            //逻辑删除
            req.setAttribute("standardId", standardId);
            List<InspectionItem> items = inspectionItemService.query(Cnd.where("insStandardId", "=", standardId));
            for (InspectionItem item : items) {
                inspectionItemService.vDelete(item.getId());
            }
            inspectionStandardService.vDelete(standardId);
            inspectionItemService.clearCache();
            inspectionStandardService.clearCache();
            return Result.success();
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return Result.error();
        }
    }

    @Aop(TransAop.READ_COMMITTED)
    @At("/batch/delete")
    @Ok("json")
    @RequiresPermissions("bus.ins_standard.management.delete")
    @SLog(tag = "批量删除标准", msg = "IDS:${args[1].getAttribute('ids')}")
    public Object batchDelete(@Param("ids") String[] ids, HttpServletRequest req) {
        try {
            req.setAttribute("ids", ids.toString());
            List<InspectionItem> items = inspectionItemService.query(Cnd.where("insStandardId", "in", ids));
            for (InspectionItem item : items) {
                inspectionItemService.vDelete(item.getId());
            }
            inspectionStandardService.vDelete(ids);
            inspectionItemService.clearCache();
            inspectionStandardService.clearCache();
            return Result.success("删除成功！");
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return Result.error();
        }
    }

    @Aop(TransAop.READ_COMMITTED)
    @At({"/itemDelete","/itemDelete/?"})
    @Ok("json")
    @RequiresPermissions("bus.ins_standard.management.delete")
    @SLog(tag = "删除项目", msg = "IDS:${args[0]}")
    public Object itemDelete(String id,@Param("ids") String[] ids, HttpServletRequest req) {
        try {
            if(ids!=null&&ids.length>0){
                inspectionItemService.delete(ids);
            }else{
                inspectionItemService.delete(id);
            }
            inspectionItemService.clearCache();
            return Result.success("删除成功！");
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return Result.error();
        }
    }

    @Aop(TransAop.READ_COMMITTED)
    @At("/importExcel/?")
    @Ok("json")
    @RequiresPermissions("bus.ins_standard.management.add")
    @SLog(tag = "批量导入标准", msg = "文件:${args[0]}")
    public Object importExcel(String fileId) {
        String msg = "";
        try {
            BusinessFileInfo reportheaderTemplate = businessFileInfoService.fetch(fileId);
            String uploadPath = this.getUploadPathConfig();
            String filePath = uploadPath+reportheaderTemplate.getFilePath();
            int headNum = 4;
            ArrayList<ArrayList<Object>> list = DoExcelUtil.readExcel(filePath,0,headNum,15);
            List<InspectionStandard> objEdit = new ArrayList<>();
            List<InspectionStandard> objlist = inspectionStandardService.listEntity(Sqls.create(" select * from  bus_ins_standard where delFlag=0 and disabled=0 "));
            List<BusEquipment> equipments = busEquipmentService.listEntity(Sqls.create(" select * from  bus_equipment where delFlag=0 "));
            Map<String, String> yplxMap0 = sysDictService.getCodeMap("yplx");
            NutMap yplxMap = new NutMap();
            for (Map.Entry<String, String> entry : yplxMap0.entrySet()){
                yplxMap.addv(entry.getValue(),entry.getKey());
            }
            Map<String, String> chargeStandardMap0 = sysDictService.getCodeMap("charge_standard");
            NutMap chargeStandardMap = new NutMap();
            for (Map.Entry<String, String> entry : chargeStandardMap0.entrySet()){
                chargeStandardMap.addv(entry.getValue(),entry.getKey());
            }
            for (int i = 0 ;i<list.size();i++) {
                ArrayList<Object> row = list.get(i);
                String rowString = row.stream().map(str -> str.toString()).collect(Collectors.joining(""));
                if(StringUtils.isNotBlank(rowString)){
                    InspectionStandard standard = new InspectionStandard();
                    if(StringUtils.isNotBlank(row.get(0).toString())){
                        standard.setProductName(row.get(0).toString());
                    }else{
                        msg+="第"+(i+1+headNum)+"行【产品名称】不能为空！";
                    }
                    if(StringUtils.isNotBlank(row.get(1).toString())&&StringUtils.isNotBlank(row.get(2).toString())){
                        String yplx1 = row.get(1).toString();
                        String yplxId1="";
                        String yplxId2="";
                        if(Objects.isNull(yplxMap.get(yplx1))){
                            msg+="第"+(i+1+headNum)+"行【产品类型】父类不存在，请保持与系统中一致！";
                        }else{
                             yplxId1 = yplxMap.get(yplx1).toString();
                        }
                        String yplx2 = row.get(2).toString();
                        if(Objects.isNull(yplxMap.get(yplx2))){
                            msg+="第"+(i+1+headNum)+"行【产品类型】子类不存在，请保持与系统中一致！";
                        }else{
                             yplxId2 = yplxMap.get(yplx2).toString();
                        }
                        if(StringUtils.isNotBlank(yplxId1)&&StringUtils.isNotBlank(yplxId2)){
                            standard.setProductTypeCode(yplxId1+","+yplxId2);
                        }
                    }
                    if(StringUtils.isNotBlank(row.get(3).toString())){
                        standard.setInspectionStandard(row.get(3).toString());
                    }else{
                        msg+="第"+(i+1+headNum)+"行【检验依据标准】不能为空！";
                    }

                    AtomicBoolean x = new AtomicBoolean(true);

                    objEdit.stream().map(t->{
                        if(t.getInspectionStandard().equals(standard.getInspectionStandard())&&t.getProductTypeCode().
                                equals(standard.getProductTypeCode())&&t.getProductName().equals(standard.getProductName())){
                            x.set(false);
                        }
                        return t;
                    }).collect(Collectors.toList());
                    if(x.get()){
                        objlist.stream().map(t->{
                            if(t.getInspectionStandard().equals(standard.getInspectionStandard())&&t.getProductTypeCode().
                                    equals(standard.getProductTypeCode())&&t.getProductName().equals(standard.getProductName())){
                                objEdit.add(t);
                                x.set(false);
                            }
                            return t;
                        }).collect(Collectors.toList());
                    }
                    if(x.get()){
                        objEdit.add(standard);
                    }
                    InspectionItem item = new InspectionItem();
                    if(StringUtils.isNotBlank(row.get(4).toString())){
                        item.setInspectionItemName(row.get(4).toString());
                    }else{
                        msg+="第"+(i+1+headNum)+"行【检验项目】不能为空！";
                    }
                    if(StringUtils.isNotBlank(row.get(5).toString())){
                        item.setInspectionItemOrder(Integer.valueOf(row.get(5).toString()));
                    }else{
                        msg+="第"+(i+1+headNum)+"行【附页序号】不能为空！";
                    }
                    if(StringUtils.isNotBlank(row.get(6).toString())){
                        item.setStandardTermsNumber(row.get(6).toString());
                    }
                    if(StringUtils.isNotBlank(row.get(7).toString())){
                        item.setSpecification(row.get(7).toString());
                    }
                    if(StringUtils.isNotBlank(row.get(8).toString())){
                        item.setSampleCount(Integer.valueOf(row.get(8).toString()));
                    }
                    if(StringUtils.isNotBlank(row.get(9).toString())){
                        item.setInspectionPrice(Float.valueOf(row.get(9).toString()));
                    }else{
                        item.setInspectionPrice(0f);
                    }
                    if(StringUtils.isNotBlank(row.get(10).toString())){
                        item.setChargeStandardName(row.get(10).toString());
                        if(chargeStandardMap.get(row.get(10).toString())!=null){
                            item.setChargeStandardCode(chargeStandardMap.get(row.get(10).toString()).toString());
                        }else{
                            msg+="第"+(i+1+headNum)+"行【收费标准】不存在，请保持与系统中一致！";
                        }
                    }
                    if(StringUtils.isNotBlank(row.get(11).toString())){
                        item.setCountUnit(row.get(11).toString());
                    }
                    if(StringUtils.isNotBlank(row.get(12).toString())){
                        item.setInspectionCycle(row.get(12).toString());
                    }else {
                        msg+="第"+(i+1+headNum)+"行【检验周期】不能为空！";
                    }
                    if(StringUtils.isNotBlank(row.get(13).toString())){
                        item.setEnvironmentStandard(row.get(13).toString());
                    }
                    if(StringUtils.isNotBlank(row.get(14).toString())){
                        String[] eCode = row.get(14).toString().split(",");
                        item.setEquipmentCode(row.get(14).toString());
                        for(int e = 0;e<eCode.length;e++){
                            AtomicBoolean b = new AtomicBoolean(true);
                            int finalE = e;
                            equipments.stream().map(t->{
                                if(t.getCode().equals(eCode[finalE])){
                                    /*item.setEquipmentId(t.getId());
                                    item.setEquipmentName(t.getName());*/
                                    b.set(false);
                                }
                                return t;
                            }).collect(Collectors.toList());
                            if(b.get()){
                                msg+="第"+(i+1+headNum)+"行【设备编号："+eCode[e]+"】不存在，请保持与系统中一致！";
                            }
                        }
                    }
                    if(StringUtils.isNotBlank(row.get(15).toString())){
                        item.setRemark(row.get(15).toString());
                    }
                    objEdit.stream().map(t->{
                        if(t.getInspectionStandard().equals(standard.getInspectionStandard())&&t.getProductTypeCode().
                                equals(standard.getProductTypeCode())&&t.getProductName().equals(standard.getProductName())){
                                if(t.getInspectionItems()==null){
                                    t.setInspectionItems(new ArrayList<InspectionItem>());
                                }
                                t.getInspectionItems().add(item);
                        }
                        return t;
                    }).collect(Collectors.toList());
                }
            }

            if(msg.equals("")){
                for (InspectionStandard standard : objEdit){
                    standard.setOpBy(StringUtil.getPlatformUid());
                    standard.setOperatorName(StringUtil.getPlatformUsername());
                    standard.setOpAt(Times.getTS());
                    inspectionStandardService.insertOrUpdate(standard);
                    for(InspectionItem item : standard.getInspectionItems()){
                        item.setOpBy(StringUtil.getPlatformUid());
                        item.setOpAt(Times.getTS());
                        item.setInsStandardId(standard.getId());
                        inspectionItemService.insertOrUpdate(item);
                    }
                }
                return Result.success("导入成功！");
            }else{
                return Result.error(msg);
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return Result.error(msg);
    }


    private String getUploadPathConfig() throws Exception {
        String uploadPath;
        //系统没开启配置,上传到项目路径
        if ("false".equals(Globals.MyConfig.getOrDefault("IsConfigUploadPath", "false"))){
            uploadPath= UploadController.class.getClassLoader().getResource("").getPath()+"upload";
        }else if (
                ("true".equals(Globals.MyConfig.getOrDefault("IsConfigUploadPath", "false")))&&(Globals.MyConfig.getOrDefault("ConfigUploadPath", null)!=null)
        ){
            uploadPath=Globals.MyConfig.get("ConfigUploadPath").toString();
        }else {
            throw new Exception("文件上传路径配置有误");
        }
        return uploadPath;
    }

}
